/**
 * tables
 * 表格组件
 */
layui.define(['component', 'layer', 'form', 'flow', 'table', 'notify', 'handle', 'methods'], function (exports) {

    var ly = layui.layer,
        o = layui.jquery,
        handle = layui.handle,
        notify = layui.notify,
        methods = layui.methods,
        dropdown = layui.dropdown,
        t = '',
        tea = false,
        u = layui.util,
        d = layui.laydate,
        f = layui.form,
        flow = layui.flow,
        global = {},
        _reserved = {
            searchLinkage: '.lay-search-linkage',
            searchDate: '.lay-search-date',
            builderTopEvent: 'builder-top-event',
            builderTable: 'builderTable',
            builderSearchEvent: 'builder-search-event',
            builderSearchForm: 'builder-search-form',
            builderEvent: 'builder-event',
            builderEventBlur: 'builder-event-blur',
            builderSwitch: 'builderSwitch',
            layOptions: 'lay-options',
            token: 'builderTableToken',
        };
    var table = {
        method: {
            getTableRowData: function (elem) {
                var index = o(elem).closest('tr').data('index');
                return layui.table.cache[_reserved.builderTable][index] || {};
            },
            getSearchFormVal: function () {
                return f.val(_reserved.builderSearchForm);
            },
            getTableCheck: function () {
                var ids = [];
                t.checkStatus(_reserved.builderTable).data.forEach(function (v, i) {
                    ids.push(v[global.pk]);
                });
                return ids.join(',');
            },
            tableReload: function () {
                t.reload(_reserved.builderTable, {
                    page: {
                        curr: o(".layui-laypage-em").next().text()
                    },
                });
            }
        }
    }
    var listen = {
        listenSearchLinkage: function () {
            o(_reserved.searchLinkage).each(function (i, v) {
                var $ = layui.jquery, mixed = o(v)[0].dataset, menus = {}, that = o(this), ID = that.attr('id');
                var hideHtml = '', value = [], deep = -1;
                mixed.field.split('-').map((v, i) => {
                    hideHtml += '<input class="hide-val ' + (ID + i) + '" type="hidden" name="' + v + '"/>'
                    deep += 1;
                });
                mixed.deep = deep;
                that.parent().append(hideHtml);
                $('#' + ID).on('click', function (e) {
                    e.stopPropagation();
                    value = [];
                    loadLevel(0, $(this));
                });

                function createMenuContainer(level) {
                    const $container = $(`
                    <div class="layui-anim layui-anim-downbit level-menu level-${level}" 
                         style="display:none;position:absolute;width:150px;max-height:300px;
                         border:1px solid #e6e6e6;background:#fff;overflow-y:auto;z-index:${666 + level}">
                        <ul class="layui-nav layui-nav-tree" style="width: 150px;background-color:#fff;color: #000"></ul>
                    </div>
                `);
                    $('body').append($container);
                    return $container;
                }

                // 加载层级数据
                async function loadLevel(level, triggerElement, parentId) {
                    // 关闭更高层级的菜单
                    closeHigherLevels(level);

                    // 获取或创建容器
                    let $container = menus[level];
                    if (!$container) {
                        $container = createMenuContainer(level);
                        menus[level] = $container;
                    }

                    // 定位容器
                    positionContainer($container, triggerElement, level);
                    let data = [];
                    let res = await methods.fetchGetPromise(mixed.url, {level: level, id: parentId}, false);

                    res.data.forEach(function (v, i) {
                        data.push({
                            id: v.id,
                            name: v.title,
                            hasChildren: level < mixed.deep
                        })
                    });

                    renderMenu($container.find('ul'), data, level);
                    $container.show();
                    setTimeout(() => {
                        triggerElement.find('.layui-icon').addClass('layui-icon-right').removeClass('layui-icon-loading-1 layui-anim layui-anim-rotate layui-anim-loop');
                    }, 100)

                    var nextVal = $('.' + ID + level).val()
                    if (nextVal) {
                        $('.level-' + level).find('.layui-nav-item[data-id="' + nextVal + '"]').click();
                    }

                }

                // 定位容器
                function positionContainer($container, trigger, level) {
                    const offset = trigger.offset();
                    $container.css({
                        top: level === 0 ? offset.top + trigger.outerHeight() + 5 : offset.top,
                        left: level === 0 ? offset.left : offset.left + trigger.outerWidth() + 5
                    });
                }

                // 渲染菜单
                function renderMenu($ul, data, level) {
                    $ul.empty().off('click');
                    data.forEach(item => {
                        const $li = $(`
                        <li class="layui-nav-item" 
                            data-id="${item.id}"
                            data-level="${level}"
                            data-name="${item.name}"
                            style="padding:2px 15px;cursor:pointer;width: calc(150px - 30px);display: flex;align-items: center;justify-content: space-between">
                            <span class="menu-item-text" style="flex: 1;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;margin-right: 8px;">${item.name}</span>
                            ${item.hasChildren ? '<i class="layui-icon layui-icon-right"></i>' : ''}
                        </li>
                    `);
                        $ul.append($li);
                    });

                    // 菜单项点击事件
                    $ul.on('click', 'li', function (e) {
                        e.stopPropagation();
                        const $this = $(this);
                        const nextLevel = level + 1;
                        let reload = false;
                        $this.addClass('active').siblings().removeClass('active');
                        $this.find('.layui-icon').removeClass('layui-icon-right').addClass('layui-icon-loading-1 layui-anim layui-anim-rotate layui-anim-loop');
                        value[level] = $this.data('name');
                        if ($this.data('id') !== parseInt(o('.' + ID + level).val())) {
                            $('.' + ID + level).val($this.data('id'));
                            reload = true;
                            for (var k = 0; k <= mixed.deep; k++) {
                                if (k > level) {
                                    $('.' + ID + k).val('');
                                    value.splice(level + 1, 1)
                                }
                            }
                        }
                        that.val(value.join(' / '));
                        if ($this.find('i').length > 0) {
                            loadLevel(nextLevel, $this, $this.data('id'));
                        } else {

                            if (reload) {
                                Object.values(menus).forEach($container => $container.hide());
                            }
                        }
                    });
                }

                function closeHigherLevels(currentLevel) {
                    Object.keys(menus).forEach(key => {
                        if (parseInt(key) > currentLevel) {
                            menus[key].hide();
                        }
                    });
                }

                $(document).on('click', function () {
                    Object.values(menus).forEach($container => $container.hide());
                });
            });
        },
        listenSearchDate: function () {
            o(_reserved.searchDate).each(function (i, v) {
                var mixed = o(v)[0].dataset;
                d.render({
                    elem: o(v),
                    type: mixed.type,
                    range: mixed.range === 'true'
                });
            })
        },
        listenButtons: function () {
            u.on(_reserved.builderTopEvent, {
                openWin: function (that, e) {
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    u.openWin({url: options.url});
                },
                submit: function (that, e) {
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    methods.confirm('确定要' + options.title + '吗？', function () {
                        return methods.fetchPostThrottle(options.url, {}, function (d) {
                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                location.reload();
                            }) : notify.error(d.msg)
                        });
                    });
                },
                add: function (that, e) {
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    let op = options.url.includes("?") ? '&' : '?';
                    let url = options.url + op + _reserved.token + '=' + global.token;
                    let title = options.layerTitle ? options.layerTitle : options.title;
                    return methods.od(title, url, options.width, options.offset ? options.offset : 'l', options.height);
                },
                newPage: function (that, e) {
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    let op = options.url.includes("?") ? '&' : '?';
                    let url = options.url + op + _reserved.token + '=' + global.token;
                    location.href = url + '&newPage=1'
                },
                prompt: function (that) {
                    var ids = table.method.getTableCheck();
                    if (!ids) {
                        notify.error('请选中要操作的数据');
                        return false;
                    }
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    let data = {};
                    data.id = ids;
                    ly.prompt({
                        title: options.title,
                        formType: options.formType,
                        placeholder: options.placeholder
                    }, function (text, index) {
                        ly.close(index);
                        data[options.name] = text;
                        return methods.fetchPostThrottle(options.url, data, function (d) {
                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                table.method.tableReload();
                            }) : notify.error(d.msg)
                        });
                    });
                },

                promptAll: function (that) {
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];
                    let data = {};
                    ly.prompt({
                        title: options.title,
                        formType: options.formType,
                        placeholder: options.placeholder
                    }, function (text, index) {
                        ly.close(index);
                        data[options.name] = text;
                        return methods.fetchPostThrottle(options.url, data, function (d) {
                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                table.method.tableReload();
                            }) : notify.error(d.msg)
                        });
                    });
                },

                batch: function (that) {
                    var ids = table.method.getTableCheck();
                    if (!ids) {
                        notify.error('请选中要操作的数据');
                        return false;
                    }
                    let options = global.top_buttons[that.attr(_reserved.layOptions)];

                    methods.confirm('确定要' + options.title + '吗？', function () {
                        return methods.fetchPostThrottle(options.url, {id: ids}, function (d) {
                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                table.method.tableReload();
                            }) : notify.error(d.msg)
                        });
                    })

                },
                deleteAll: function (that) {
                    var ids = table.method.getTableCheck();
                    if (!ids) {
                        notify.error('请选中要删除的数据');
                        return false;
                    }
                    var options = global.top_buttons[that.attr(_reserved.layOptions)];
                    methods.confirm('确定要删除已选中的数据吗？', function () {
                        return methods.fetchPostThrottle(options.url, {id: ids}, function (d) {
                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                table.method.tableReload();
                            }) : notify.error(d.msg)
                        });
                    })

                },
                tableExport: function (that) {
                    var options = global.top_buttons[that.attr(_reserved.layOptions)], fVal;
                    if (!options.url && !options.exportUrl) {
                        notify.error('未配置导出数据源url');
                        return false;
                    }
                    fVal = f.val(_reserved.builderSearchForm);
                    fVal.searchOpen = 1;
                    fVal.exportCheckIds = table.method.getTableCheck();
                    methods.load()
                    methods.fetchGet(options.exportUrl ? options.exportUrl : options.url, fVal, function (d) {
                        methods.closeLoad();
                        if (options.exportUrl) {
                            d.type === 'json' ? methods.downloadJson(d.data, d.title) : u.openWin({url: d.data})
                        } else {
                            t.exportFile(_reserved.builderTable, d.data, {
                                type: options.exportType,
                                title: options.exportTitle,
                            });
                        }

                    }, false);
                },
                expandAll: function (that) {
                    t.expandAll(_reserved.builderTable, !tea);
                    tea = !tea;
                    that.html(tea ? '<i class="layui-icon layui-icon-folder-open"></i> 折叠全部' : '<i class="layui-icon layui-icon-folder"></i> 展开全部');
                    flow.lazyimg({elem: '.lazy-images'});
                },


                customEvent: function (that) {
                    var options = global.top_buttons[that.attr(_reserved.layOptions)];
                    if (o.isFunction(handle.top[options.customEvent])) {
                        return handle.top[options.customEvent](that, options, table.method);
                    } else {
                        notify.error('handle.js顶部按钮回调区域未定义【' + options.customEvent + '】方法，请先定义后再调用！');
                    }
                }
            });

            u.on(_reserved.builderSearchEvent, {
                search: function () {
                    var val = table.method.getSearchFormVal();
                    val.searchOpen = 1;
                    o(".builder-reset").removeClass("layui-hide");
                    t.reloadData(_reserved.builderTable, {where: val, page: {curr: 1}});
                },
                clear: function () {
                    t.reloadData(_reserved.builderTable, {where: '', page: {curr: 1}});
                    o(".builder-reset").addClass("layui-hide");
                }
            });

            u.on(_reserved.builderEvent, {
                photos: function (that) {
                    //搜寻父级data-content
                    const content = o(that).parents("td[data-content]").attr("data-content");
                    let data = [];
                    if (content) {
                        content.split(',').forEach((v, i) => {
                            data.push({
                                "pid": i,
                                "src": v,
                            });
                        })
                    } else {
                        data.push({src: o(that).attr("src")})
                    }
                    ly.photos({photos: {"data": data, "start": 0}, anim: 5, closeBtn: 1});
                },
                video: function (that) {
                    const previewUrl = o(that).attr("src");
                    ly.open({
                        type: 1,
                        title: false,
                        area: ['800px', '500px'],
                        content: '<div style="display: flex;align-items: center;justify-content: center;padding: 10px;background-color: #000;"><video src="' + previewUrl + '" controls="controls" style="width: auto;height: 480px;"></video></div>'
                    });
                }
            });

            u.on(_reserved.builderEventBlur, {
                sort: function (that, e) {
                    var mixed = o(that)[0].dataset, update = {};
                    update[mixed.filed] = o(that).val();
                    methods.fetchPost(global.fastSort[mixed.filed].fastSort, {
                        id: mixed.id,
                        update: update,
                        rowData: table.method.getTableRowData(that)
                    }, function (d) {
                        if (d.code !== 1) notify.error(d.msg);
                        // rowData[mixed.filed] = o(that).val()
                    }, false)
                }
            }, {
                trigger: 'blur'
            });
        },
        listenBuilderTable: function () {
            var height = o(window).height(), limit = 20, fVal = f.val(_reserved.builderSearchForm),
                tree, view;
            Object.values(fVal).forEach(function (v, i) {
                if (v !== '') fVal.searchOpen = 1;
            });

            global.tree ? tree = {
                customName: global.treeConfig.customName,
                view: global.treeConfig.view,
                callback: {
                    onExpand: function (tableId, trData, expandFlag) {
                        flow.lazyimg({elem: '.lazy-images'});
                    }
                }
            } : tree = {};

            t.render({
                elem: '#' + _reserved.builderTable,
                id: _reserved.builderTable,
                url: global.url + '?builderTableToken=' + global.token,
                where: fVal,
                page: true,
                cellMinWidth: 80,
                autoSort: false,
                limit: limit,
                limits: [10, 15, 20, 30, 40, 60, 80, 100],
                size: global.config.size,
                skin: global.config.skin,
                width: global.config.width,
                height: global.config.height ? global.config.height : '',
                lineStyle: global.config.lineStyle,
                className: global.config.className,
                tree: tree,
                totalRow: global.totalRow,
                cols: [global.columns],
                done: function (res, curr, count) {

                    o(".layui-table-main tr").each(function (index, val) {
                        o(o(".layui-table-fixed-l .layui-table-body tbody tr")[index]).height(o(val).height());
                        o(o(".layui-table-fixed-r .layui-table-body tbody tr")[index]).height(o(val).height());
                    });

                    if (global.treeConfig.view.expandAllDefault) {
                        tea = true;
                        o('button[builder-top-event="expandAll"]').html('<i class="layui-icon layui-icon-folder-open"></i> 折叠全部');
                    }

                    setTimeout(function () {
                        let opt = {elem: '.lazy-images'}
                        if (o(document).height() > o(window).height()) {
                            opt.scrollElem = o('body')
                        }
                        flow.lazyimg(opt);
                    }, 200)

                    t.on('sort(' + _reserved.builderTable + ')', function (obj) {
                        t.reload(_reserved.builderTable, {
                            initSort: obj,
                            where: {tableSort: [obj.field, obj.type].join(',')}
                        });
                    });

                    f.on('switch(' + _reserved.builderSwitch + ')', function (data) {
                        var mixed = o(data.elem)[0].dataset,
                            ops = global.switch[mixed.filed].switch,
                            checkedVal = ops.val.split('|'),
                            update = {},
                            rowData = table.method.getTableRowData(data.elem)

                        update[mixed.filed] = data.elem.checked ? checkedVal[0] : checkedVal[1];
                        methods.fetchPost(ops.url, {
                            id: mixed.id,
                            update: update,
                            rowData: rowData
                        }, function (d) {
                            if (d.code !== 1) notify.error(d.msg);
                            rowData[mixed.filed] = data.elem.checked ? checkedVal[0] : checkedVal[1]
                        }, false)

                    });

                    t.on('tool(' + _reserved.builderTable + ')', function (obj) {
                        const options = global.right_buttons[o(this).attr(_reserved.layOptions)];
                        const data = obj.data;
                        switch (obj.event) {
                            case "edit":
                            case "od":
                            case "layer":
                            case "newPage":
                                let op = options.url.includes("?") ? '&' : '?';
                                let fd = '';
                                if (options.urlParam) {
                                    options.urlParam.split(',').forEach((v, i) => {
                                        v = v.split(':');
                                        fd += (i === 0 ? op : '&') + v[0] + '=' + data[v[1]];
                                    });
                                } else {
                                    if (options.lineParam) {
                                        let n = {id: data.id};
                                        options.lineParam.split(',').forEach((v, i) => {
                                            n[v] = data[v];
                                        });
                                        op += o.param(n)
                                    } else {
                                        op += (global.pk + '=' + data.id);
                                    }
                                    fd = op;
                                }
                                let url = options.url + fd + "&" + _reserved.token + '=' + global.token;
                                let title = options.layerTitle ? options.layerTitle : o(this).text();
                                if (obj.event === 'newPage') {
                                    location.href = url + '&newPage=1'
                                } else {
                                    obj.event === 'layer'
                                        ? methods.openFormLayer(title, url, options.width)
                                        : methods.od(title, url, options.width, options.offset ? options.offset : 'r', options.height);
                                }
                                break;
                            case "delete":
                            case "submit":
                                let ti = obj.event === 'delete' ? '删除' : options.title
                                let pd = '';
                                if (options.lineParam) {
                                    let n = {id: data.id};
                                    options.lineParam.split(',').forEach((v, i) => {
                                        n[v] = data[v];
                                    });
                                    pd = n
                                } else {
                                    pd = {id: data.id}
                                }

                                methods.confirm('确定要' + ti + '吗？', function () {
                                    return methods.fetchPostThrottle(options.url, pd, function (d) {
                                        if (obj.event === 'delete') {
                                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                                obj.del();
                                            }) : notify.error(d.msg)
                                        } else {
                                            d.code === 1 ? notify.success(d.msg, 1000, function () {
                                                location.reload()
                                            }) : notify.error(d.msg)
                                        }
                                    });
                                })
                                break;
                            default:
                                if (o.isFunction(handle.right[options.customEvent])) {
                                    return handle.right[options.customEvent](o(this), data, options);
                                } else {
                                    notify.error('handle.js右侧按钮回调区域未定义【' + options.customEvent + '】方法，请先定义后再调用！');
                                }
                        }
                    });
                }
            });
        },
        listenPreload: function () {
            for (const action in handle.preload) {
                const that = o('button[preload-options="' + action + '"]')
                if (that.length > 0) {
                    handle.preload[action](that, global.top_buttons[action], table.method);
                }
            }
        }
    }
    var component = layui.component({
        name: 'tables',
        config: {},
        render: function () {
            layui.methods.getGlobal().then(data => {
                global = data;
                t = global.tree ? layui.treeTable : layui.table
                notify.init();
                listen.listenSearchLinkage();
                listen.listenSearchDate();
                listen.listenButtons();
                listen.listenBuilderTable();
                listen.listenPreload();
            });
        }
    });

    layui.$.extend(component, {

        method: table.method,
        listen: listen
    });

    exports(component.CONST.MOD_NAME, component);
});